From cf4cd4fe930b72bc54df64da78bd8f998db7ecee Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Mon, 22 Sep 2025 13:43:03 +0200 Subject: [PATCH 1/7] wip --- package.json | 3 ++- tests/helper.mjs | 56 ++++++++++++++++++++++++++++++++++++++++++- tests/run-shell.mjs | 58 +++------------------------------------------ 3 files changed, 60 insertions(+), 57 deletions(-) diff --git a/package.json b/package.json index db7aca4..3cdbae5 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/tests/helper.mjs b/tests/helper.mjs index 0867e8a..e2aa80a 100644 --- a/tests/helper.mjs +++ b/tests/helper.mjs @@ -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; @@ -80,3 +81,56 @@ 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); + 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(); + } +} + + +const SPAWN_OPTIONS = { + stdio: ["inherit", "inherit", "inherit"] +}; + + +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); + }) +} diff --git a/tests/run-shell.mjs b/tests/run-shell.mjs index 1b626a7..b4f04c3 100644 --- a/tests/run-shell.mjs +++ b/tests/run-shell.mjs @@ -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]." }, @@ -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; From 50644f8b5e8896f760ee35b19340afaacc176cb4 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Mon, 22 Sep 2025 13:43:13 +0200 Subject: [PATCH 2/7] wip --- tests/run-build.mjs | 55 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 tests/run-build.mjs diff --git a/tests/run-build.mjs b/tests/run-build.mjs new file mode 100644 index 0000000..b9c1d63 --- /dev/null +++ b/tests/run-build.mjs @@ -0,0 +1,55 @@ + +import { exec as exec_callback } from 'child_process'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; +import { promisify } from 'util'; +import fs from fs; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const root = join(__dirname, '..'); + +async function findPackageJsonFiles(dir, accumulator=[]) { + const dirEntries = await fs.readdir(dir, { withFileTypes: true }); + for (const dirent of dirEntries) { + if (dirent.name === 'node_modules' || dirent.name === '.git') + continue; + const res = join(dir, dirent.name); + if (dirent.isDirectory()) { + findPackageJsonFiles(res, accumulator); + } + if (dirent.name === 'package.json') { + accumulator.push(res) + } + } + return accumulator; +} + +async function main() { + const packageJsonFiles = await findPackageJsonFiles(root); + for (const file of packageJsonFiles) { + const content = await readFile(file, 'utf-8'); + const packageJson = JSON.parse(content); + if (packageJson.scripts && packageJson.scripts.build) { + const dir = dirname(file); + console.log(`Found build script in ${dir}`); + try { + console.log(`Running "npm install" in ${dir}...`); + await exec('npm install', { cwd: dir }); + console.log(`Running "npm run build" in ${dir}...`); + await exec('npm run build', { cwd: dir }); + console.log(`Successfully built ${packageJson.name}`); + console.log('Resetting repository...'); + await exec('git reset --hard'); + console.log('Repository reset.'); + } catch (e) { + console.error(`Failed to build ${packageJson.name}: ${e}`); + process.exit(1); + } + } + } +} + +main().catch(e => { + console.error(e); + process.exit(1); +}); From c646d718cfa8d801e113426fa256ac6e3cb0a300 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Mon, 22 Sep 2025 13:48:47 +0200 Subject: [PATCH 3/7] wip --- tests/run-build.mjs | 68 ++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/tests/run-build.mjs b/tests/run-build.mjs index b9c1d63..527d1dc 100644 --- a/tests/run-build.mjs +++ b/tests/run-build.mjs @@ -1,12 +1,23 @@ +#! /usr/bin/env node -import { exec as exec_callback } from 'child_process'; +import commandLineArgs from "command-line-args"; +import fs from "fs"; import { dirname, join } from 'path'; import { fileURLToPath } from 'url'; -import { promisify } from 'util'; -import fs from fs; -const __dirname = dirname(fileURLToPath(import.meta.url)); -const root = join(__dirname, '..'); +import { logError, 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 = await fs.readdir(dir, { withFileTypes: true }); @@ -24,32 +35,33 @@ async function findPackageJsonFiles(dir, accumulator=[]) { return accumulator; } -async function main() { - const packageJsonFiles = await findPackageJsonFiles(root); +async function runBuilds() { + const packageJsonFiles = await findPackageJsonFiles(SRC_DIR); + let success = true; + for (const file of packageJsonFiles) { - const content = await readFile(file, 'utf-8'); + const content = await fs.readFile(file, 'utf-8'); const packageJson = JSON.parse(content); - if (packageJson.scripts && packageJson.scripts.build) { - const dir = dirname(file); - console.log(`Found build script in ${dir}`); - try { - console.log(`Running "npm install" in ${dir}...`); - await exec('npm install', { cwd: dir }); - console.log(`Running "npm run build" in ${dir}...`); - await exec('npm run build', { cwd: dir }); - console.log(`Successfully built ${packageJson.name}`); - console.log('Resetting repository...'); - await exec('git reset --hard'); - console.log('Repository reset.'); - } catch (e) { - console.error(`Failed to build ${packageJson.name}: ${e}`); - process.exit(1); - } + if (!packageJson.scripts?.build) { + continue; } + + const dir = dirname(file); + const testName = `Building ${packageJson.name || dir}`; + + const buildTask = async () => { + await sh('npm', 'install', '--prefix', dir); + await sh('npm', 'run', 'build', '--prefix', dir); + await sh('git', 'reset', '--hard'); + }; + + success &&= await runTest(testName, buildTask); + } + + if (!success) { + logError("One or more builds failed."); + process.exit(1); } } -main().catch(e => { - console.error(e); - process.exit(1); -}); +setImmediate(runBuilds); \ No newline at end of file From c22b0b68b015da771c46c11d89c810cf92d426b9 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Mon, 22 Sep 2025 13:59:36 +0200 Subject: [PATCH 4/7] fix --- tests/run-build.mjs | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/tests/run-build.mjs b/tests/run-build.mjs index 527d1dc..b82b51d 100644 --- a/tests/run-build.mjs +++ b/tests/run-build.mjs @@ -2,8 +2,8 @@ import commandLineArgs from "command-line-args"; import fs from "fs"; -import { dirname, join } from 'path'; -import { fileURLToPath } from 'url'; +import { fileURLToPath } from "url"; +import path from "path"; import { logError, printHelp, runTest, sh } from "./helper.mjs"; @@ -20,17 +20,15 @@ const FILE_PATH = fileURLToPath(import.meta.url); const SRC_DIR = path.dirname(path.dirname(FILE_PATH)); async function findPackageJsonFiles(dir, accumulator=[]) { - const dirEntries = await fs.readdir(dir, { withFileTypes: true }); + const dirEntries = fs.readdirSync(dir, { withFileTypes: true }); for (const dirent of dirEntries) { - if (dirent.name === 'node_modules' || dirent.name === '.git') + if (dirent.name === "node_modules" || dirent.name === ".git") continue; - const res = join(dir, dirent.name); - if (dirent.isDirectory()) { - findPackageJsonFiles(res, accumulator); - } - if (dirent.name === 'package.json') { - accumulator.push(res) - } + const fullPath = path.join(dir, dirent.name); + if (dirent.isDirectory()) + findPackageJsonFiles(fullPath, accumulator); + else if (dirent.name === "package.json") + accumulator.push(fullPath) } return accumulator; } @@ -40,19 +38,25 @@ async function runBuilds() { let success = true; for (const file of packageJsonFiles) { - const content = await fs.readFile(file, 'utf-8'); + const content = fs.readFileSync(file, "utf-8"); const packageJson = JSON.parse(content); if (!packageJson.scripts?.build) { continue; } - const dir = dirname(file); - const testName = `Building ${packageJson.name || dir}`; + const dir = path.dirname(file); + const testName = `Building ${dir}`; const buildTask = async () => { - await sh('npm', 'install', '--prefix', dir); - await sh('npm', 'run', 'build', '--prefix', dir); - await sh('git', 'reset', '--hard'); + const oldCWD = process.cwd(); + try { + 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); From c648ba98c807bb5c102523e9afe92b45636c9e1c Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Mon, 22 Sep 2025 14:18:01 +0200 Subject: [PATCH 5/7] add missing package --- tests/helper.mjs | 27 ++++++++++++--------------- tests/run-build.mjs | 2 +- web-ssr/package-lock.json | 7 +++++++ web-ssr/package.json | 1 + 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/tests/helper.mjs b/tests/helper.mjs index e2aa80a..03edb86 100644 --- a/tests/helper.mjs +++ b/tests/helper.mjs @@ -93,33 +93,30 @@ export async function sh(binary, ...args) { 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; + 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"] +}); -const SPAWN_OPTIONS = { - stdio: ["inherit", "inherit", "inherit"] -}; - - -async function spawnCaptureStdout(binary, args) { - const childProcess = spawn(binary, args); +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) => { + childProcess.on("close", (code) => { if (code === 0) { resolve(childProcess); } else { @@ -131,6 +128,6 @@ async function spawnCaptureStdout(binary, args) { reject(error); } }); - childProcess.on('error', reject); + childProcess.on("error", reject); }) } diff --git a/tests/run-build.mjs b/tests/run-build.mjs index b82b51d..6e14ee8 100644 --- a/tests/run-build.mjs +++ b/tests/run-build.mjs @@ -55,7 +55,7 @@ async function runBuilds() { await sh("npm", "run", "build"); } finally { process.chdir(oldCWD); - await sh("git", "reset", "--hard"); + // await sh("git", "reset", "--hard"); } }; diff --git a/web-ssr/package-lock.json b/web-ssr/package-lock.json index cba3e15..561c631 100644 --- a/web-ssr/package-lock.json +++ b/web-ssr/package-lock.json @@ -14,6 +14,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", @@ -1641,6 +1642,12 @@ "node": ">=6.9.0" } }, + "node_modules/@dapplets/unicode-escape-webpack-plugin": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@dapplets/unicode-escape-webpack-plugin/-/unicode-escape-webpack-plugin-0.1.1.tgz", + "integrity": "sha512-dBcrCWE6ZOOHD1XLe3raXk29CwQSJQCXYx8QNcCMvfG+cZ9tZh1h2OVV7D936pmues8OTm1KhjWeiZXbH30SAg==", + "license": "MIT" + }, "node_modules/@discoveryjs/json-ext": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz", diff --git a/web-ssr/package.json b/web-ssr/package.json index 973d193..1f58b47 100644 --- a/web-ssr/package.json +++ b/web-ssr/package.json @@ -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", From 7f6b7f1f4b1437f6bb802c1b84d21a867f95c523 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Mon, 22 Sep 2025 15:12:28 +0200 Subject: [PATCH 6/7] fixes --- .github/workflows/test.yml | 9 +++++++-- tests/helper.mjs | 18 ++++++++++++------ tests/run-build.mjs | 6 ++++-- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e3014f8..3470191 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,8 +10,8 @@ on: workflow_dispatch: jobs: - build: - name: Build + test: + name: Test runs-on: macos-latest env: GITHUB_ACTIONS_OUTPUT: "" @@ -49,3 +49,8 @@ jobs: run: | echo "Running in $BROWSER" npm run test:${{ matrix.browser }} + + - name: Run Build + run: | + echo "Running in $BROWSER" + npm run test:build \ No newline at end of file diff --git a/tests/helper.mjs b/tests/helper.mjs index 03edb86..1dc5be2 100644 --- a/tests/helper.mjs +++ b/tests/helper.mjs @@ -31,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); @@ -83,15 +93,11 @@ export async function runTest(label, testFunction) { } - export async function sh(binary, ...args) { const cmd = `${binary} ${args.join(" ")}`; - if (GITHUB_ACTIONS_OUTPUT) { + if (GITHUB_ACTIONS_OUTPUT) core.startGroup(binary); - core.notice(styleText("blue", cmd)); - } else { - console.log(styleText("blue", cmd)); - } + logCommand(cmd); try { return await spawnCaptureStdout(binary, args); } catch(e) { diff --git a/tests/run-build.mjs b/tests/run-build.mjs index 6e14ee8..213b0e9 100644 --- a/tests/run-build.mjs +++ b/tests/run-build.mjs @@ -5,7 +5,7 @@ import fs from "fs"; import { fileURLToPath } from "url"; import path from "path"; -import { logError, printHelp, runTest, sh } from "./helper.mjs"; +import { logError, logCommand, printHelp, runTest, sh } from "./helper.mjs"; const optionDefinitions = [ { name: "help", alias: "h", description: "Print this help text." }, @@ -45,11 +45,13 @@ async function runBuilds() { } const dir = path.dirname(file); - const testName = `Building ${dir}`; + 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"); From a18962c4489ae6348fe597b7fd8050c625c16956 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Mon, 22 Sep 2025 15:25:33 +0200 Subject: [PATCH 7/7] format --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3470191..f3a72c6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -53,4 +53,4 @@ jobs: - name: Run Build run: | echo "Running in $BROWSER" - npm run test:build \ No newline at end of file + npm run test:build