mirror of
https://github.com/pdfme/pdfme.git
synced 2026-04-19 21:49:03 -04:00
fix: revert parallel test runner to vp sequential execution
The custom parallel test runner (run-workspace-tests.mjs) caused flaky UI snapshot tests due to CPU contention during parallel execution. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -41,7 +41,7 @@
|
||||
"fmt:meta": "vp fmt -c .oxfmtrc.json package.json packages/cli/package.json packages/common/package.json packages/converter/package.json packages/generator/package.json packages/manipulator/package.json packages/pdf-lib/package.json packages/schemas/package.json packages/ui/package.json playground/package.json .oxlintrc.json .oxfmtrc.json playground/.oxlintrc.json vite.config.mts --write",
|
||||
"ci": "npm run check && npm run build && npm --prefix playground run build",
|
||||
"typecheck": "node packages/common/set-version.cjs && tsc -b",
|
||||
"test": "node scripts/run-workspace-tests.mjs",
|
||||
"test": "vp run --filter '@pdfme/*' test",
|
||||
"lint": "vp run --filter '@pdfme/*' lint && npm --prefix playground run lint",
|
||||
"lint:fix": "vp lint -c .oxlintrc.json packages/cli/src packages/common/src packages/converter/src packages/generator/src packages/manipulator/src packages/pdf-lib/src packages/schemas/src packages/ui/src --fix && npm --prefix playground run lint -- --fix"
|
||||
},
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { spawn } from 'node:child_process';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const repoRoot = path.resolve(__dirname, '..');
|
||||
const forwardArgs = process.argv.slice(2);
|
||||
|
||||
const rootPackageJson = JSON.parse(readFileSync(path.join(repoRoot, 'package.json'), 'utf8'));
|
||||
const workspaces = rootPackageJson.workspaces.filter((workspace) =>
|
||||
readWorkspacePackageJson(workspace).scripts?.test,
|
||||
);
|
||||
|
||||
const defaultConcurrency = Math.min(
|
||||
workspaces.length,
|
||||
Math.max(2, Math.min(4, os.availableParallelism?.() ?? os.cpus().length)),
|
||||
);
|
||||
const concurrency = parseConcurrency(process.env.PDFME_TEST_CONCURRENCY, defaultConcurrency);
|
||||
|
||||
const failures = [];
|
||||
const durations = new Map();
|
||||
let queueIndex = 0;
|
||||
|
||||
console.log(`[root:test] Running ${workspaces.length} workspace test suites with concurrency ${concurrency}.`);
|
||||
|
||||
await Promise.all(
|
||||
Array.from({ length: concurrency }, async () => {
|
||||
while (queueIndex < workspaces.length) {
|
||||
const workspace = workspaces[queueIndex];
|
||||
queueIndex += 1;
|
||||
const result = await runWorkspaceTest(workspace);
|
||||
durations.set(workspace, result.durationMs);
|
||||
if (result.code !== 0) {
|
||||
failures.push(workspace);
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
for (const workspace of workspaces) {
|
||||
const durationMs = durations.get(workspace) ?? 0;
|
||||
const status = failures.includes(workspace) ? 'failed' : 'passed';
|
||||
console.log(`[root:test] ${workspace} ${status} in ${formatDuration(durationMs)}`);
|
||||
}
|
||||
|
||||
if (failures.length > 0) {
|
||||
console.error(`[root:test] ${failures.length} workspace test run(s) failed.`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function readWorkspacePackageJson(workspace) {
|
||||
return JSON.parse(readFileSync(path.join(repoRoot, workspace, 'package.json'), 'utf8'));
|
||||
}
|
||||
|
||||
function parseConcurrency(value, fallback) {
|
||||
const parsed = Number(value);
|
||||
if (!Number.isInteger(parsed) || parsed < 1) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
return Math.min(parsed, workspaces.length);
|
||||
}
|
||||
|
||||
function runWorkspaceTest(workspace) {
|
||||
const label = path.basename(workspace);
|
||||
const args = ['run', 'test', '-w', workspace];
|
||||
if (forwardArgs.length > 0) {
|
||||
args.push('--', ...forwardArgs);
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const start = Date.now();
|
||||
const child = spawn('npm', args, {
|
||||
cwd: repoRoot,
|
||||
env: process.env,
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
});
|
||||
|
||||
pipeOutput(child.stdout, label, false);
|
||||
pipeOutput(child.stderr, label, true);
|
||||
|
||||
child.on('close', (code) => {
|
||||
resolve({
|
||||
code: code ?? 1,
|
||||
durationMs: Date.now() - start,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function pipeOutput(stream, label, useErrorStream) {
|
||||
let buffer = '';
|
||||
|
||||
stream.on('data', (chunk) => {
|
||||
buffer += chunk.toString();
|
||||
buffer = flushCompleteLines(buffer, label, useErrorStream);
|
||||
});
|
||||
|
||||
stream.on('end', () => {
|
||||
if (buffer.length > 0) {
|
||||
writeLine(label, buffer, useErrorStream);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function flushCompleteLines(buffer, label, useErrorStream) {
|
||||
const lines = buffer.split(/\r?\n/);
|
||||
const remainder = lines.pop() ?? '';
|
||||
|
||||
for (const line of lines) {
|
||||
writeLine(label, line, useErrorStream);
|
||||
}
|
||||
|
||||
return remainder;
|
||||
}
|
||||
|
||||
function writeLine(label, line, useErrorStream) {
|
||||
if (line.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const writer = useErrorStream ? console.error : console.log;
|
||||
writer(`[${label}] ${line}`);
|
||||
}
|
||||
|
||||
function formatDuration(durationMs) {
|
||||
return `${(durationMs / 1000).toFixed(2)}s`;
|
||||
}
|
||||
Reference in New Issue
Block a user